﻿using System;
using System.Collections.Generic;

namespace IInject.Resolution.Activation
{
	/// <summary>
	/// 
	/// </summary>
	public class DefaultDependencyActivator : ITypeDependencyActivator
	{
		/// <summary>
		/// 
		/// </summary>
		public DefaultDependencyActivator()
		{
			PropertyActivator = new PropertyDependencyActivator(this);
		}

		protected IPropertyDependencyActivator PropertyActivator { get; private set; }

		public T Activate<T>(TypeDependency dependency)
		{
			return (T)Activate(dependency);
		}

		public object Activate(TypeDependency dependency)
		{
			if (dependency.Scope == Scope.Singleton && dependency.Instance != null)
			{
				return dependency.Instance;
			}

			var dependencies = dependency.Constructor.Dependencies;
			var instance = Create(dependency, dependencies);
			if (dependency.Scope == Scope.Singleton)
			{
				dependency.Instance = instance;
			}

			return instance;
		}

		protected object[] Activate(IList<TypeDependency> dependencies)
		{
			var parameters = new object[dependencies.Count];

			if (dependencies.Count > 0)
			{
				for (var i = 0; i < dependencies.Count; i++)
				{
					parameters[i] = Activate(dependencies[i]);
				}
			}

			return parameters;
		}

		private object Create(TypeDependency type, IList<TypeDependency> dependencies)
		{
			var instance = Activator.CreateInstance(type.Dependent, Activate(dependencies));

			if (type.Dependencies.Count > 0)
			{
				var properties = type.Dependencies;

				for (int i = 0; i < properties.Count; i++)
				{
					PropertyActivator.Activate(properties[i], instance);
				}
			}

			return instance;
		}
	}
}
